package com.alibaba.citrus.ots.application.report.ability.facade.service;

import com.alibaba.citrus.ots.application.report.ability.utils.DomUtil;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.cz.base.model.store.enums.CargoZoneTypeEnum;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.alibaba.lattice2.epoch.sdk.model.annotation.EpochAPI;
import com.epoch.app.bcorder.model.dto.BaselineBatchQueryChannels2Request;
import com.epoch.app.bcorder.model.dto.ChannelSDO;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.otsapplicationreportsdk.ecinventorydetail.dto.GetPlatformByGoodsIdRequest;
import com.epoch.app.otsapplicationreportsdk.ecinventorydetail.dto.StaticByPlatformAndGoodsRequest;
import com.epoch.app.otsapplicationreportsdk.ecinventorydetail.model.EcInventoryDetail;
import com.epoch.app.otsapplicationreportsdk.ecinventorydetail.service.EcInventoryDetailService;
import com.epoch.app.otsapplicationreportsdk.ecinventorystats.dto.StatisByPlatformRequest;
import com.epoch.app.otsapplicationreportsdk.ecinventorystats.model.EcInventoryStats;
import com.epoch.app.otsapplicationreportsdk.ecinventorystats.service.EcInventoryStatsService;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetAvailableNodesRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetAvailableNodesResponse;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetCurveModuleDataRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetCurveModuleDataResponse;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetGoodsRankRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetPieListRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.GetStoreRankRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.QueryBoardForMobileRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.dto.QueryBoardForPCRequest;
import com.epoch.app.otsapplicationreportsdk.inventoryboard.service.InventoryBoardService;
import com.epoch.app.otsapplicationreportsdk.model.dto.DailyMobileResponse;
import com.epoch.app.otsapplicationreportsdk.model.dto.DataInfo;
import com.epoch.app.otsapplicationreportsdk.model.dto.InventoryRankInfo;
import com.epoch.app.otsapplicationreportsdk.model.dto.ModuleInfo;
import com.epoch.app.otsapplicationreportsdk.model.dto.PieData;
import com.epoch.app.otsapplicationreportsdk.model.dto.PieInfo;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankAppComponent;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankAppComponentContent;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankAppComponentData;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankData;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankTab;
import com.epoch.app.otsapplicationreportsdk.model.dto.RankViewVO;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListForPageRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListForPageResponse;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.model.StoreInventoryDetail;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.service.StoreInventoryDetailService;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.QueryByStoreIdsRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.QueryGroupByChannelCodeRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.model.StoreInventoryStats;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.service.StoreInventoryStatsService;
import com.epoch.app.otsapplicationreportsdk.warehouseinventorystats.dto.QueryByWarehouseAreaIdsRequest;
import com.epoch.app.otsapplicationreportsdk.warehouseinventorystats.dto.SumGroupByStatisticalDateRequest;
import com.epoch.app.otsapplicationreportsdk.warehouseinventorystats.model.WarehouseInventoryStats;
import com.epoch.app.otsapplicationreportsdk.warehouseinventorystats.service.WarehouseInventoryStatsService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class InventoryBoardServiceImpl implements InventoryBoardService {

    private static Log log = Log.getLogger(InventoryBoardServiceImpl.class);
    private static final String[] arrayThreeMonth = {"排行", "网点名称", "前三个月库存数量（件）"};
    private static final String[] arrayFourMonth = {"排行", "网点名称", "四个月前库存数量（件）"};

    private final String RANK_SORTFIELD_THREEMONTHSQUANTITY = "threeMonthsQuantity";
    private final String RANK_SORTFIELD_FOURMONTHSQUANTITY = "fourMonthsQuantity";

    @Resource
    WarehouseInventoryStatsService warehouseInventoryStatsService;
    @Resource
    StoreInventoryDetailService storeInventoryDetailService;
    @Resource
    StoreInventoryStatsService storeInventoryStatsService;
    @Resource
    EcInventoryStatsService ecInventoryStatsService;
    @Resource
    EcInventoryDetailService ecInventoryDetailService;
    @Resource
    CrPlatformEnhanceService otsPlatformEnhanceService;
    @Resource
    BaseDataService baseDataService;

    private final static int PAGE_SIZE_500 = 500;

    @Override
    public Object queryBoardForPC(QueryBoardForPCRequest queryBoardForPCRequest) {
        log.info("queryBoardForPC_request={}", JSON.toJSONString(queryBoardForPCRequest));
        JSONObject jsonObject = new JSONObject();
        try {
            Map<String, Object> result = new HashMap<>();
            List<OrganizationSDO> organizationSDOS = getBranchCompanyList();
            String branchCompanyId = queryBoardForPCRequest.getBranchCompanyId();
            if (StringUtils.isBlank(branchCompanyId)) {
                branchCompanyId = organizationSDOS.get(0).getId();
                result.put("branchCompanyId", branchCompanyId);
                result.put("branchCompanyName", organizationSDOS.get(0).getName());
            } else {
                result.put("branchCompanyId", branchCompanyId);
                result.put("branchCompanyName", getBranchCompanyName(organizationSDOS, branchCompanyId));
            }

            Date statisticalDate = new Date();
            //获取仓库库存
            List<WarehouseInventoryStats> inventoryStats = this.getWarehouseInventoryStatsListCopy(branchCompanyId,
                DateUtils.formatDate(statisticalDate, null));
            result.put("availableNodes", this.buildAvailableData(inventoryStats));
            result.put("expiredNodes", this.buildExpiredData(inventoryStats));
            List<StoreInventoryStats> storeStats = this.getStoreInventoryStatsList(branchCompanyId,
                DateUtils.formatDate(statisticalDate, null));
            result.put("mixNodes", this.buildOnWayData(inventoryStats, storeStats));
            result.put("wareDomPie", buildWarehouseInventoryDom(inventoryStats));
            result.put("expiredPie", buildExpiredPie(inventoryStats));
            result.put("storeDomPie", buildStoreInventoryDom(storeStats));
            jsonObject.put("success", true);
            jsonObject.put("result", result);
            jsonObject.put("title", "库存KPI报表");
        } catch (Exception e) {
            jsonObject.put("success", false);
            jsonObject.put("title", "库存KPI报表");
            jsonObject.put("msg", e.getMessage());
        }
        log.info("jsonObject_result={}", JSON.toJSONString(jsonObject));
        return jsonObject;
    }

    @EpochAPI(api = "InventoryBoard$queryBoardForEC")
    @Override
    public Object queryBoardForEC() {
        JSONObject result = new JSONObject();
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("expiredPie", buildPlatformPie());
            jsonObject.put("rankList", buildRankInfo());
            result.put("result", jsonObject);
            result.put("success", true);
        } catch (Exception e) {
            result.put("success", false);
            result.put("msg", e.getMessage());
        }
        return result;
    }

    @Override
    public Object queryBoardForMobile(QueryBoardForMobileRequest queryBoardForMobileRequest) {
        log.info("queryBoardForMobile_request={}", JSON.toJSONString(queryBoardForMobileRequest));
        String statisticalDate = queryBoardForMobileRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        JSONObject jsonObject = new JSONObject();
        try {
            Map<String, Object> result = new HashMap<>();
            List<OrganizationSDO> organizationSDOS = getBranchCompanyList();
            String branchCompanyId = queryBoardForMobileRequest.getBranchCompanyId();
            if (StringUtils.isBlank(branchCompanyId)) {
                branchCompanyId = organizationSDOS.get(0).getId();
                result.put("branchCompanyId", branchCompanyId);
                result.put("branchCompanyName", organizationSDOS.get(0).getName());
            } else {
                result.put("branchCompanyId", branchCompanyId);
                result.put("branchCompanyName", getBranchCompanyName(organizationSDOS, branchCompanyId));
            }
            //获取仓库库存
            List<WarehouseInventoryStats> inventoryStats = getWarehouseInventoryStatsList(branchCompanyId,statisticalDate);
            result.put("availableNodes", this.buildAvailableData(inventoryStats));
            result.put("expiredNodes", this.buildExpiredData(inventoryStats));
            List<StoreInventoryStats> storeStats = getStoreInventoryStatsList(branchCompanyId, statisticalDate);
            result.put("mixNodes", this.buildOnWayData(inventoryStats, storeStats));

            result.put("curveModule", buildCurveModule(branchCompanyId, statisticalDate));

            List<PieInfo> pieList = new ArrayList<>();
            pieList.add(buildWarehouseInventoryDom(inventoryStats));
            pieList.add(buildExpiredPie(inventoryStats));
            pieList.add(buildStoreInventoryDom(storeStats));
            result.put("pieModule", pieList);

            List<StoreInventoryStats> channelStoreStatsList = new ArrayList<>();
            Map<String,List<StoreInventoryStats>> channelStoreStatsMap = new HashMap<>();
            Map<String,ChannelSDO> channelMap = new HashMap<>();
            if(CollectionUtils.isNotEmpty(storeStats)){
                //根据业务渠道分组网点库存排序
                channelStoreStatsList = this.getStoreInventoryGroupByChannelCodeStatsList(branchCompanyId, statisticalDate);
                channelStoreStatsMap = channelStoreStatsList.stream().filter(x->StringUtils.isNotBlank(x.getChannelCode()))
                        .collect(Collectors.groupingBy(x->x.getChannelCode()));
                //查询业务渠道
                List channelCodes = channelStoreStatsMap.keySet().stream().collect(Collectors.toList());
                BaselineBatchQueryChannels2Request queryChannelsRequest = new BaselineBatchQueryChannels2Request();
                queryChannelsRequest.setChannelCodes(channelCodes);
                Result<List<ChannelSDO>> channelResult = baseDataService.baselineBatchQueryChannels2(queryChannelsRequest);
                if(Objects.nonNull(channelResult) && CollectionUtils.isNotEmpty(channelResult.getResult())){
                    channelMap = channelResult.getResult().stream().collect(Collectors.toMap(x->x.getChannelCode(), Function.identity(),(v1, v2)->v1));
                }
            }
            result.put("threeMonthsStoreRank", buildStoreRank(RANK_SORTFIELD_THREEMONTHSQUANTITY,storeStats,channelStoreStatsMap,channelMap));
            result.put("fourMonthsStoreRank", buildStoreRank(RANK_SORTFIELD_FOURMONTHSQUANTITY,storeStats,channelStoreStatsMap,channelMap));

            List<StoreInventoryDetail> storeDetails = getStoreInventoryDetailList(branchCompanyId, statisticalDate);
            result.put("goodsRank", buildGoodsRank(storeDetails));

            jsonObject.put("success", true);
            jsonObject.put("result", result);
            jsonObject.put("title", "库存KPI报表");
        } catch (Exception e) {
            jsonObject.put("success", false);
            jsonObject.put("title", "库存KPI报表");
            jsonObject.put("msg", e.getMessage());
            log.error("queryBoardForMobile_error_cause={}", e);
        }
        log.info("queryBoardForMobile_jsonObject_result={}", JSON.toJSONString(jsonObject));
        return jsonObject;
    }

    @Override
    public GetAvailableNodesResponse getAvailableNodes(GetAvailableNodesRequest getAvailableNodesRequest) {
        String statisticalDate = getAvailableNodesRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        String branchCompanyId = getAvailableNodesRequest.getBranchCompanyId();
        GetAvailableNodesResponse response = new GetAvailableNodesResponse();
        Map<String, Object> result = new HashMap<>();
        try {
            //获取仓库库存
            List<WarehouseInventoryStats> inventoryStats = this.getWarehouseInventoryStatsList(branchCompanyId,
                statisticalDate);
            if (CollectionUtils.isNotEmpty(inventoryStats)) {
                result.put("availableNodes", this.buildAvailableData(inventoryStats));
                result.put("expiredNodes", this.buildExpiredData(inventoryStats));
            } else {
                result.put("availableNodes", this.initAvailableData());
                result.put("expiredNodes", this.initExpiredData());
            }
            List<StoreInventoryStats> storeStats = this.getStoreInventoryStatsList(branchCompanyId, statisticalDate);
            result.put("mixNodes", this.buildOnWayData(inventoryStats, storeStats));
            response.setResult(result);
            response.setSuccess(true);
        } catch (Exception e) {
            log.error("getAvailableNodes_error_cause={}", e);
            response.setSuccess(false);
        }
        return response;
    }

    @Override
    public GetCurveModuleDataResponse getCurveModuleData(GetCurveModuleDataRequest getCurveModuleDataRequest) {
        String statisticalDate = getCurveModuleDataRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        Date statDate = DateUtils.parse(statisticalDate);
        String branchCompanyId = getCurveModuleDataRequest.getBranchCompanyId();
        String thisMonthDate = DomUtil.getMonth(statDate);
        String lastMonthDate = DomUtil.getLastMonthByDate(statDate);

        GetCurveModuleDataResponse response = new GetCurveModuleDataResponse();
        Map<String, Object> result = new HashMap<>();
        List<DailyMobileResponse> lastMonth = new ArrayList<>();
        List<WarehouseInventoryStats> statsOfLastMonth = this.sumGroupByStatisticalDate(branchCompanyId, lastMonthDate);
        Date firstDayLastMonth = DomUtil.getFirstDayLastMonth(statDate);
        int maxDayLastMonth = DomUtil.getMaxDayLastMonth(statDate);
        for (int i = 0; i < maxDayLastMonth; i++) {
            String date = DomUtil.getRollbackDate(firstDayLastMonth, i);
            DailyMobileResponse data = new DailyMobileResponse();
            data.setNum(new BigDecimal(0));
            data.setValue("0");
            List<WarehouseInventoryStats> subList = statsOfLastMonth.stream().filter(
                s -> date.equals(s.getStatisticalDate())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(subList)) {
                WarehouseInventoryStats stats = subList.get(0);
                BigDecimal quantity = new BigDecimal(stats.getAvailableQuantity());
                data.setNum(quantity.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
                data.setValue(DomUtil.quantityFormatWan(stats.getAvailableQuantity()) + "万件");
            }
            lastMonth.add(data);
        }
        result.put("lastMonth", lastMonth);

        List<DailyMobileResponse> currentMonth = new ArrayList<>();
        List<WarehouseInventoryStats> statsOfThisMonth = this.sumGroupByStatisticalDate(branchCompanyId, thisMonthDate);
        Date firstDayThisMonth = DomUtil.getStartTimeOfMonth(statDate);
        int todayOfMonth = DomUtil.getTodayOfMonth(statDate);
        for (int i = 0; i < todayOfMonth; i++) {
            DailyMobileResponse data = new DailyMobileResponse();
            String date = DomUtil.getRollbackDate(firstDayThisMonth, i);
            data.setNum(new BigDecimal(0));
            data.setValue("0");
            List<WarehouseInventoryStats> subList = statsOfThisMonth.stream().filter(
                s -> date.equals(s.getStatisticalDate())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(subList)) {
                WarehouseInventoryStats stats = subList.get(0);
                BigDecimal quantity = new BigDecimal(stats.getAvailableQuantity());
                data.setNum(quantity.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
                data.setValue(DomUtil.quantityFormatWan(stats.getAvailableQuantity()) + "万件");
            }
            currentMonth.add(data);
        }
        result.put("currentMonth", currentMonth);
        result.put("statisticalDate", statisticalDate);
        response.setResult(result);
        return response;
    }

    @Override
    public Result<List<PieInfo>> getPieList(GetPieListRequest getPieListRequest) {
        String statisticalDate = getPieListRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        List result = new ArrayList();
        String branchCompanyId = getPieListRequest.getBranchCompanyId();
        try {
            List<WarehouseInventoryStats> inventoryStats = this.getWarehouseInventoryStatsList(branchCompanyId,statisticalDate);
            result.add(buildWarehouseInventoryDom(inventoryStats).getContent());
            result.add(buildExpiredPie(inventoryStats).getContent());
            List<StoreInventoryStats> storeStats = this.getStoreInventoryStatsList(branchCompanyId, statisticalDate);
            result.add(buildStoreInventoryDom(storeStats).getContent());
        } catch (Exception e) {
            log.error("getPieList_error_cause={}", e);
            throw new FacadeException(ErrorMessage.code("OTS-01-010-01-15-004"));
        }
        return Result.listSuccess(result, result.size());
    }

    @Override
    @FacadeInvoker
    public Result<List<RankViewVO>> getStoreRank(GetStoreRankRequest getStoreRankRequest) {
        String statisticalDate = getStoreRankRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        String branchCompanyId = getStoreRankRequest.getBranchCompanyId();
        List<RankViewVO> result = new ArrayList();
        try {
            List<StoreInventoryStats> storeStats = this.getStoreInventoryStatsList(branchCompanyId, statisticalDate);

            List<StoreInventoryStats> channelStoreStatsList = new ArrayList<>();
            Map<String,List<StoreInventoryStats>> channelStoreStatsMap = new HashMap<>();
            Map<String,ChannelSDO> channelMap = new HashMap<>();
            if(CollectionUtils.isNotEmpty(storeStats)){
                //根据业务渠道分组网点库存排序
                channelStoreStatsList = this.getStoreInventoryGroupByChannelCodeStatsList(branchCompanyId, statisticalDate);
                channelStoreStatsMap = channelStoreStatsList.stream().filter(x->StringUtils.isNotBlank(x.getChannelCode()))
                        .collect(Collectors.groupingBy(x->x.getChannelCode()));
                //查询业务渠道
                List channelCodes = channelStoreStatsMap.keySet().stream().collect(Collectors.toList());
                BaselineBatchQueryChannels2Request queryChannelsRequest = new BaselineBatchQueryChannels2Request();
                queryChannelsRequest.setChannelCodes(channelCodes);
                Result<List<ChannelSDO>> channelResult = baseDataService.baselineBatchQueryChannels2(queryChannelsRequest);
                if(Objects.nonNull(channelResult) && CollectionUtils.isNotEmpty(channelResult.getResult())){
                    channelMap = channelResult.getResult().stream().collect(Collectors.toMap(x->x.getChannelCode(), Function.identity(),(v1, v2)->v1));
                }
            }

            if(Objects.equals(1,getStoreRankRequest.getBizType())){
                result = assembleRankViewVOList(storeStats,channelStoreStatsMap,channelMap,RANK_SORTFIELD_THREEMONTHSQUANTITY);
            }else if(Objects.equals(2,getStoreRankRequest.getBizType())){
                result = assembleRankViewVOList(storeStats,channelStoreStatsMap,channelMap,RANK_SORTFIELD_FOURMONTHSQUANTITY);
            }else{
                throw new RuntimeException("bizType入参错误");
            }
        } catch (Exception e) {
            log.error("getStoreRank_error_cause={}", e);
            throw new FacadeException(ErrorMessage.code("OTS-01-010-01-15-004"));
        }
        return Result.listSuccess(result, result.size());
    }

    private List<RankViewVO> assembleRankViewVOList(List<StoreInventoryStats> storeStats,Map<String,List<StoreInventoryStats>> channelStoreStatsMap,Map<String,ChannelSDO> channelMap,String sortField){
        List<RankViewVO> result = new ArrayList();
        if(CollectionUtils.isEmpty(storeStats)){
            return result;
        }
        List<RankData> data = assembleRankData(storeStats,sortField);
        if(CollectionUtils.isEmpty(data)){
            return result;
        }
        String str = sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)?"前三个月":"四个月前";
        RankTab tab = RankTab.builder().sortNo("排序").label("网点名称").quantity(str+"库存数量（件）").build();
        RankViewVO vo = RankViewVO.builder()
                .title(str+"库存TOP10网点（全业务渠道）")
                .tab(tab)
                .data(data)
                .build();
        result.add(vo);
        for (Map.Entry<String,List<StoreInventoryStats>> m : channelStoreStatsMap.entrySet()) {
            String channelCode = m.getKey();
            List<StoreInventoryStats> channelStoreStats = m.getValue();
            ChannelSDO channelSDO = channelMap.get(channelCode);
            if(Objects.isNull(channelSDO)){
                continue;
            }
            List<RankData> channelData = assembleRankData(channelStoreStats,sortField);
            if(CollectionUtils.isEmpty(channelData)){
               continue;
            }
            RankViewVO vo2 = RankViewVO.builder()
                    .title(str+"库存TOP10网点（"+channelSDO.getChannelName()+"渠道)")
                    .tab(tab)
                    .data(channelData)
                    .build();
            result.add(vo2);
        }
        return result;
    }

    private List<RankData> assembleRankData(List<StoreInventoryStats> storeStats,String sortField){
        if(CollectionUtils.isEmpty(storeStats)){
            return new ArrayList<>();
        }
        List<StoreInventoryStats> sortStoreStats = new ArrayList<>();
        Long maxOne = 0L;
        if(sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)){
            sortStoreStats = storeStats.stream().filter(x->!x.getThreeMonthsQuantity().equals(0L)).sorted(
                    Comparator.comparing(StoreInventoryStats::getThreeMonthsQuantity).reversed()).collect(Collectors.toList());
            maxOne = CollectionUtils.isNotEmpty(sortStoreStats)?sortStoreStats.get(0).getThreeMonthsQuantity():0L;
        }else{
            sortStoreStats = storeStats.stream().filter(x->!x.getFourMonthsQuantity().equals(0L)).sorted(
                    Comparator.comparing(StoreInventoryStats::getFourMonthsQuantity).reversed()).collect(Collectors.toList());
            maxOne = CollectionUtils.isNotEmpty(sortStoreStats)?sortStoreStats.get(0).getFourMonthsQuantity():0L;
        }
        sortStoreStats = sortStoreStats.size() > 10 ? sortStoreStats.subList(0, 10) : sortStoreStats;
        //Long last = threeMonthStats.get(0).getThreeMonthsQuantity();
        //Integer lastNo = 0;
        Integer sortNo = 0;
        List<RankData> content = new ArrayList<>();
        for (StoreInventoryStats stats : sortStoreStats) {
            Long quantity = sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)?stats.getThreeMonthsQuantity():stats.getFourMonthsQuantity();
            sortNo++;
            RankData data = new RankData();
            data.setLabel(stats.getStoreName());
            if (maxOne > 0) {
                BigDecimal process = new BigDecimal(quantity).multiply(new BigDecimal(100))
                        .divide(new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                data.setProgress(process);
            }
            data.setSortNo(sortNo);
            //                if (sortNo!=1 && stats.getThreeMonthsQuantity().equals(last)){
            //                    data.setSortNo(lastNo);
            //                }
            //                lastNo = data.getSortNo();
            //                last = stats.getThreeMonthsQuantity();
            data.setQuantity(DomUtil.quantityFormatJian(quantity));
            content.add(data);
        }
        return content;
    }

    @Override
    public Result<List<RankData>> getGoodsRank(GetGoodsRankRequest getGoodsRankRequest) {
        String statisticalDate = getGoodsRankRequest.getStatisticalDate();
        if (StringUtil.isBlank(statisticalDate)) {
            statisticalDate = DomUtil.getToday();
        }
        String branchCompanyId = getGoodsRankRequest.getBranchCompanyId();
        List result = new ArrayList();
        try {
            List<StoreInventoryDetail> storeDetails = this.getStoreInventoryDetailList(branchCompanyId,statisticalDate);
            if (CollectionUtils.isEmpty(storeDetails)) {
                return Result.listSuccess(result, result.size());
            }
            List<StoreInventoryDetail> sumByGoodsIdList = new ArrayList<>();
            Map<String, List<StoreInventoryDetail>> mapGoods = storeDetails.stream().collect(
                Collectors.groupingBy(x -> x.getGoodsId()));
            for (Map.Entry<String, List<StoreInventoryDetail>> entry : mapGoods.entrySet()) {
                StoreInventoryDetail sumByGoodsId = new StoreInventoryDetail();
                List<StoreInventoryDetail> subList = entry.getValue();
                sumByGoodsId.setGoodsName(subList.get(0).getGoodsName());
                Long threeMonthSum = subList.stream().mapToLong(StoreInventoryDetail::getThreeMonthsQuantity).sum();
                sumByGoodsId.setThreeMonthsQuantity(threeMonthSum);
                Long fourMonthSum = subList.stream().mapToLong(StoreInventoryDetail::getFourMonthsQuantity).sum();
                sumByGoodsId.setFourMonthsQuantity(fourMonthSum);
                sumByGoodsIdList.add(sumByGoodsId);
            }

            List<StoreInventoryDetail> threeMonthStats = sumByGoodsIdList.stream().filter(x->!x.getThreeMonthsQuantity().equals(0L))
                    .sorted(Comparator.comparing(StoreInventoryDetail::getThreeMonthsQuantity).reversed()).collect(Collectors.toList());
            threeMonthStats = threeMonthStats.size() > 10 ? threeMonthStats.subList(0, 10) : threeMonthStats;
            Long maxOne = CollectionUtils.isNotEmpty(threeMonthStats)?threeMonthStats.get(0).getThreeMonthsQuantity():0L;
            //Long last = threeMonthStats.get(0).getThreeMonthsQuantity();
            //Integer lastNo = 0;
            Integer sortNo = 0;
            List<RankData> content = new ArrayList<>();
            for (StoreInventoryDetail stats : threeMonthStats) {
                sortNo++;
                RankData info = new RankData();
                info.setLabel(stats.getGoodsName());
                if (maxOne > 0) {
                    BigDecimal process = new BigDecimal(stats.getThreeMonthsQuantity()).multiply(new BigDecimal(100))
                        .divide(new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                    info.setProgress(process);
                }
                info.setSortNo(sortNo);
                //                if (sortNo!=1 && stats.getThreeMonthsQuantity().equals(last)){
                //                    info.setSortNo(lastNo);
                //                }
                //                last = stats.getThreeMonthsQuantity();
                //                lastNo = info.getSortNo();
                info.setQuantity(DomUtil.quantityFormatJian(stats.getThreeMonthsQuantity()));
                content.add(info);
            }
            result.add(content);

            List<StoreInventoryDetail> fourMonthStats = sumByGoodsIdList.stream().filter(x->!x.getFourMonthsQuantity().equals(0L))
                    .sorted(Comparator.comparing(StoreInventoryDetail::getFourMonthsQuantity).reversed()).collect(Collectors.toList());
            fourMonthStats = fourMonthStats.size() > 10 ? fourMonthStats.subList(0, 10) : fourMonthStats;
            maxOne = CollectionUtils.isNotEmpty(fourMonthStats)?fourMonthStats.get(0).getFourMonthsQuantity():0L;
            //last = fourMonthStats.get(0).getFourMonthsQuantity();
            sortNo = 0;
            List<RankData> fourContent = new ArrayList<>();
            for (StoreInventoryDetail stats : fourMonthStats) {
                sortNo++;
                RankData info = new RankData();
                info.setLabel(stats.getGoodsName());
                if (maxOne > 0) {
                    BigDecimal process = new BigDecimal(stats.getFourMonthsQuantity()).multiply(new BigDecimal(100))
                        .divide(new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                    info.setProgress(process);
                }
                info.setSortNo(sortNo);
                //                if (sortNo!=1 && stats.getFourMonthsQuantity().equals(last)){
                //                    info.setSortNo(lastNo);
                //                }
                //                last = stats.getFourMonthsQuantity();
                //                lastNo = info.getSortNo();
                info.setQuantity(DomUtil.quantityFormatJian(stats.getFourMonthsQuantity()));
                fourContent.add(info);
            }
            result.add(fourContent);
        } catch (Exception e) {
            log.error("getGoodsRank_error_cause={}", e);
            throw new FacadeException(ErrorMessage.code("OTS-01-010-01-15-004"));
        }
        return Result.listSuccess(result, result.size());
    }

    //仓库库存统计报表
    private List<WarehouseInventoryStats> getWarehouseInventoryStatsList(String branchCompanyId,
        String statisticalDate) {
        QueryByWarehouseAreaIdsRequest request = new QueryByWarehouseAreaIdsRequest();
        request.setStatisticalDate(statisticalDate);
        request.setBizUnitId(branchCompanyId);
        Result<List<WarehouseInventoryStats>> result = warehouseInventoryStatsService.queryByWarehouseAreaIds(request);
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return new ArrayList<>();
        }
        //2022.03.25  全局库存看板只计算销售单元仓和共享仓
        List<WarehouseInventoryStats> zList = result.getResult().stream().filter(s ->
            CargoZoneTypeEnum.SHARE_CARGOZONE.getType().equals(Integer.valueOf(s.getZoneType()))
                || CargoZoneTypeEnum.SALE_UNIT_CARGOZONE.getType().equals(Integer.valueOf(s.getZoneType())))
            .collect(Collectors.toList());
        return zList;
    }

    //仓库库存统计报表
    private List<WarehouseInventoryStats> getWarehouseInventoryStatsListCopy(String branchCompanyId,
        String statisticalDate) {
        QueryByWarehouseAreaIdsRequest request = new QueryByWarehouseAreaIdsRequest();
        request.setStatisticalDate(statisticalDate);
        request.setBizUnitId(branchCompanyId);
        Result<List<WarehouseInventoryStats>> result = warehouseInventoryStatsService.queryByWarehouseAreaIds(request);
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return new ArrayList<>();
        }
        //2022.03.25  全局库存看板只计算销售单元仓和共享仓
        //        List<WarehouseInventoryStats> zList = result.getResult().stream().filter(s->
        //                        CargoZoneTypeEnum.SHARE_CARGOZONE.getType().equals(Integer.valueOf(s.getZoneType())
        //                        ) || CargoZoneTypeEnum.SALE_UNIT_CARGOZONE.getType().equals(Integer.valueOf(s
        //                        .getZoneType())))
        //                .collect(Collectors.toList());
        return result.getResult();
    }

    private List<WarehouseInventoryStats> sumGroupByStatisticalDate(String branchCompanyId, String statisticalMonth) {
        SumGroupByStatisticalDateRequest request = new SumGroupByStatisticalDateRequest();
        request.setStatisticalMonth(statisticalMonth);
        request.setBizUnitId(branchCompanyId);
        Result<List<WarehouseInventoryStats>> result = warehouseInventoryStatsService.sumGroupByStatisticalDate(
            request);
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return new ArrayList<>();
        }
        return result.getResult();
    }

    //网点库存统计报表
    private List<StoreInventoryStats> getStoreInventoryStatsList(String branchCompanyId, String statisticalDate) {
        QueryByStoreIdsRequest query = new QueryByStoreIdsRequest();
        query.setStatisticalDate(statisticalDate);
        query.setBizUnitId(branchCompanyId);
        Result<List<StoreInventoryStats>> result = storeInventoryStatsService.queryByStoreIds(query);
        log.info("QueryByStoreIdsRequest={},getStoreInventoryStatsList={}", JSON.toJSONString(query), JSON.toJSONString(result));
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return new ArrayList<>();
        }
        return result.getResult();
    }

    private List<StoreInventoryStats> getStoreInventoryGroupByChannelCodeStatsList(String branchCompanyId, String statisticalDate) {
        QueryGroupByChannelCodeRequest query = new QueryGroupByChannelCodeRequest();
        query.setStatisticalDate(statisticalDate);
        query.setBizUnitId(branchCompanyId);
        Result<List<StoreInventoryStats>> result = storeInventoryStatsService.queryGroupByChannelCode(query);
        log.info("QueryGroupByChannelCodeRequest={},getStoreInventoryStatsList={}", JSON.toJSONString(query),JSON.toJSONString(result));
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return new ArrayList<>();
        }
        return result.getResult();
    }

    //网点库存明细报表
    private List<StoreInventoryDetail> getStoreInventoryDetailList(String branchCompanyId, String statisticalDate) {
        List<StoreInventoryDetail> result = new ArrayList<>();
        LoadListForPageRequest query = new LoadListForPageRequest();
        query.setStatisticalDate(statisticalDate);
        query.setBizUnitId(branchCompanyId);
        query.setStart(0);
        query.setLimit(PAGE_SIZE_500);
        log.info("QueryByStoreIdsRequest={}", JSON.toJSONString(query));
        LoadListForPageResponse response = storeInventoryDetailService.loadListForPage(query);
        int total = response.getTotal();
        int totalPage = total / PAGE_SIZE_500;
        if (response.getTotal() % PAGE_SIZE_500 > 0) {
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            query.setStart(pageNo*PAGE_SIZE_500);
            query.setLimit(PAGE_SIZE_500);
            response = storeInventoryDetailService.loadListForPage(query);
            result.addAll(response.getResult());
        }
        return result;
    }

    private List initAvailableData() {
        List result = new ArrayList();

        List<DataInfo> dataSource1 = new ArrayList<>();
        DataInfo allAvailable = new DataInfo();
        allAvailable.setLabel("总在仓可用（万件）");
        dataSource1.add(allAvailable);

        DataInfo allWithholding = new DataInfo();
        allWithholding.setLabel("总在仓占用（万件）");
        dataSource1.add(allWithholding);
        result.add(dataSource1);

        List<DataInfo> dataSource2 = new ArrayList<>();
        DataInfo shareAvailable = new DataInfo();
        shareAvailable.setLabel("共享仓可用（万件）");
        dataSource2.add(shareAvailable);

        DataInfo shareWithholding = new DataInfo();
        shareWithholding.setLabel("共享仓占用（万件）");
        dataSource2.add(shareWithholding);
        result.add(dataSource2);

        List<DataInfo> dataSource3 = new ArrayList<>();
        DataInfo saleUnitAvailable = new DataInfo();
        saleUnitAvailable.setLabel("销售单元仓可用（万件）");
        dataSource3.add(saleUnitAvailable);

        DataInfo saleUnitWithholding = new DataInfo();
        saleUnitWithholding.setLabel("销售单元仓占用（万件）");
        dataSource3.add(saleUnitWithholding);
        result.add(dataSource3);

        return result;
    }

    //构建可用库存数据
    private List buildAvailableData(List<WarehouseInventoryStats> inventoryStats) {
        List result = new ArrayList();
        BigDecimal big = new BigDecimal(DomUtil.TEN_THOUSAND);
        BigDecimal ths = new BigDecimal(DomUtil.ONE_THOUSAND);
        BigDecimal ams = big.multiply(ths);

        List<DataInfo> dataSource1 = new ArrayList<>();
        DataInfo allAvailable = new DataInfo();
        allAvailable.setLabel("总在仓可用(万件)");
        BigDecimal available = new BigDecimal(
            inventoryStats.stream().mapToLong(WarehouseInventoryStats::getAvailableQuantity).sum());
        BigDecimal availableWan = available.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        allAvailable.setValue(DomUtil.quantityFormatDecimal(availableWan));

        DataInfo allWithholding = new DataInfo();
        allWithholding.setLabel("总在仓占用(万件)");
        BigDecimal withholding = new BigDecimal(
            inventoryStats.stream().mapToLong(WarehouseInventoryStats::getWithholdingQuantity).sum());
        BigDecimal withholdingWan = withholding.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        allWithholding.setValue(DomUtil.quantityFormatDecimal(withholdingWan));

        DataInfo allTotal = new DataInfo();
        allTotal.setLabel("总在仓总库存(万件)");
        BigDecimal quantity = availableWan.add(withholdingWan);
        allTotal.setValue(DomUtil.quantityFormatDecimal(quantity));

        dataSource1.add(allTotal);
        dataSource1.add(allAvailable);
        dataSource1.add(allWithholding);
        result.add(dataSource1);

        List<DataInfo> dataSource2 = new ArrayList<>();
        List<WarehouseInventoryStats> shareList = inventoryStats.stream().filter(
            s -> CargoZoneTypeEnum.SHARE_CARGOZONE.getType().equals(Integer.valueOf(s.getZoneType()))).collect(
            Collectors.toList());
        DataInfo shareAvailable = new DataInfo();
        shareAvailable.setLabel("共享仓可用(万件)");
        available = new BigDecimal(shareList.stream().mapToLong(WarehouseInventoryStats::getAvailableQuantity).sum());
        availableWan = available.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        shareAvailable.setValue(DomUtil.quantityFormatDecimal(availableWan));

        DataInfo shareWithholding = new DataInfo();
        shareWithholding.setLabel("共享仓占用(万件)");
        withholding = new BigDecimal(
            shareList.stream().mapToLong(WarehouseInventoryStats::getWithholdingQuantity).sum());
        withholdingWan = withholding.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        shareWithholding.setValue(DomUtil.quantityFormatDecimal(withholdingWan));

        DataInfo shareTotal = new DataInfo();
        shareTotal.setLabel("共享仓总库存(万件)");
        quantity = availableWan.add(withholdingWan);
        String shareTotalValue = DomUtil.quantityFormatDecimal(quantity);
        shareTotal.setValue(shareTotalValue);

        dataSource2.add(shareTotal);
        dataSource2.add(shareAvailable);
        dataSource2.add(shareWithholding);
        result.add(dataSource2);

        List<DataInfo> dataSource3 = new ArrayList<>();
        List<WarehouseInventoryStats> saleUnitList = inventoryStats.stream().filter(
            s -> CargoZoneTypeEnum.SALE_UNIT_CARGOZONE.getType().equals(Integer.valueOf(s.getZoneType()))).collect(
            Collectors.toList());
        DataInfo saleUnitAvailable = new DataInfo();
        saleUnitAvailable.setLabel("单元仓可用(万件)");
        available = new BigDecimal(
            saleUnitList.stream().mapToLong(WarehouseInventoryStats::getAvailableQuantity).sum());
        availableWan = available.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        saleUnitAvailable.setValue(DomUtil.quantityFormatDecimal(availableWan));

        DataInfo saleUnitWithholding = new DataInfo();
        saleUnitWithholding.setLabel("单元仓占用(万件)");
        withholding = new BigDecimal(
            saleUnitList.stream().mapToLong(WarehouseInventoryStats::getWithholdingQuantity).sum());
        withholdingWan = withholding.divide(ams).setScale(2, BigDecimal.ROUND_HALF_UP);
        saleUnitWithholding.setValue(DomUtil.quantityFormatDecimal(withholdingWan));

        DataInfo saleUnitTotal = new DataInfo();
        saleUnitTotal.setLabel("单元仓总库存(万件)");
        quantity = availableWan.add(withholdingWan);
        String saleUnitTotalValue = DomUtil.quantityFormatDecimal(quantity);
        saleUnitTotal.setValue(saleUnitTotalValue);

        dataSource3.add(saleUnitTotal);
        dataSource3.add(saleUnitAvailable);
        dataSource3.add(saleUnitWithholding);
        result.add(dataSource3);

        return result;
    }

    //构建临期库存数据
    private List<DataInfo> buildExpiredData(List<WarehouseInventoryStats> inventoryStats) {
        List<DataInfo> dataSource = new ArrayList<>();

        Long availableQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getAvailableQuantity).sum();
        DataInfo thirdExpiredNode = new DataInfo();
        Long thirdExpiredQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getThirdExpiredQuantity)
            .sum();
        DataInfo percent = DomUtil.decimalFormat(thirdExpiredQuantity, availableQuantity);
        thirdExpiredNode.setLabel("超保1/3库存");
        thirdExpiredNode.setValue(percent.getValue() + percent.getTail());
        thirdExpiredNode.setDesc("数量 " + DomUtil.quantityFormatWan(thirdExpiredQuantity) + "万件");
        dataSource.add(thirdExpiredNode);

        DataInfo fourthExpiredNode = new DataInfo();
        Long fourthExpiredQuantity = inventoryStats.stream().mapToLong(
            WarehouseInventoryStats::getFourthExpiredQuantity).sum();
        percent = DomUtil.decimalFormat(fourthExpiredQuantity, availableQuantity);
        fourthExpiredNode.setLabel("超保1/4库存");
        fourthExpiredNode.setValue(percent.getValue() + percent.getTail());
        fourthExpiredNode.setDesc("数量 " + DomUtil.quantityFormatWan(fourthExpiredQuantity) + "万件");
        dataSource.add(fourthExpiredNode);

        DataInfo approachExpiredNode = new DataInfo();
        Long approachExpiredQuantity = inventoryStats.stream().mapToLong(
            WarehouseInventoryStats::getApproachExpiredQuantity).sum();
        percent = DomUtil.decimalFormat(approachExpiredQuantity, availableQuantity);
        approachExpiredNode.setLabel("总临期库存");
        approachExpiredNode.setValue(percent.getValue() + percent.getTail());
        approachExpiredNode.setDesc("数量 " + DomUtil.quantityFormatWan(approachExpiredQuantity) + "万件");
        dataSource.add(approachExpiredNode);

        return dataSource;
    }

    //构建在途库存数据
    private List<DataInfo> buildOnWayData(List<WarehouseInventoryStats> inventoryStats,
        List<StoreInventoryStats> storeStats) {
        List<DataInfo> dataSource = new ArrayList<>();

        DataInfo onwayNode = new DataInfo();
        onwayNode.setLabel("总在途(万件)");
        if (CollectionUtils.isNotEmpty(inventoryStats)) {
            String onwayQuantity = DomUtil.quantityFormatWan(
                inventoryStats.stream().mapToLong(WarehouseInventoryStats::getOnwayQuantity).sum());
            onwayNode.setValue(onwayQuantity);
        }
        dataSource.add(onwayNode);

        DataInfo storeNode = new DataInfo();
        storeNode.setLabel("网点库存(件)");
        if (CollectionUtils.isNotEmpty(storeStats)) {
            String storeQuantity = DomUtil.quantityFormatJian(
                storeStats.stream().mapToLong(StoreInventoryStats::getAvailableQuantity).sum());
            storeNode.setValue(storeQuantity);
        }
        dataSource.add(storeNode);
        return dataSource;
    }

    //构建曲线图
    private List<DailyMobileResponse> buildCurveModule(String branchCompanyId, String statisticalDate) {
        Date statDate = DateUtils.parse(statisticalDate);
        String thisMonthDate = DomUtil.getMonth(statDate);
        String lastMonthDate = DomUtil.getLastMonthByDate(statDate);
        List<DailyMobileResponse> dataList = new ArrayList<>();
        List<WarehouseInventoryStats> statsOfLastMonth = this.sumGroupByStatisticalDate(branchCompanyId, lastMonthDate);
        Date firstDayLastMonth = DomUtil.getFirstDayLastMonth(statDate);
        int maxDayLastMonth = DomUtil.getMaxDayLastMonth(statDate);
        for (int i = 0; i < maxDayLastMonth; i++) {
            String date = DomUtil.getRollbackDate(firstDayLastMonth, i);
            DailyMobileResponse data = new DailyMobileResponse();
            data.setDay(DomUtil.convertDate(date));
            data.setName("lastMonth");
            data.setNum(new BigDecimal(0));
            data.setValue("0");
            List<WarehouseInventoryStats> subList = statsOfLastMonth.stream().filter(
                s -> date.equals(s.getStatisticalDate())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(subList)) {
                WarehouseInventoryStats stats = subList.get(0);
                BigDecimal quantity = new BigDecimal(stats.getAvailableQuantity());
                data.setNum(quantity.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
                data.setValue(DomUtil.quantityFormatWan(stats.getAvailableQuantity()) + "万");
            }
            dataList.add(data);
        }

        List<WarehouseInventoryStats> statsOfThisMonth = this.sumGroupByStatisticalDate(branchCompanyId, thisMonthDate);
        Date firstDayThisMonth = DomUtil.getStartTimeOfMonth(statDate);
        int todayOfMonth = DomUtil.getTodayOfMonth(statDate);
        for (int i = 0; i < todayOfMonth; i++) {
            DailyMobileResponse data = new DailyMobileResponse();
            String date = DomUtil.getRollbackDate(firstDayThisMonth, i);
            data.setDay(DomUtil.convertDate(date));
            data.setName("currMonth");
            data.setNum(new BigDecimal(0));
            data.setValue("0");
            List<WarehouseInventoryStats> subList = statsOfThisMonth.stream().filter(
                s -> date.equals(s.getStatisticalDate())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(subList)) {
                WarehouseInventoryStats stats = subList.get(0);
                BigDecimal quantity = new BigDecimal(stats.getAvailableQuantity());
                data.setNum(quantity.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
                data.setValue(DomUtil.quantityFormatWan(stats.getAvailableQuantity()) + "万");
            }
            dataList.add(data);
        }
        return dataList;
    }

    //构建网点库存饼图
    private PieInfo buildStoreInventoryDom(List<StoreInventoryStats> inventoryStats) {
        Long exceedFourMonthsQuantity = inventoryStats.stream().mapToLong(StoreInventoryStats::getFourMonthsQuantity).sum();
        Long threeMonthsQuantity = inventoryStats.stream().mapToLong(StoreInventoryStats::getThreeMonthsQuantity).sum();
        Long twoMonthsQuantity = inventoryStats.stream().mapToLong(StoreInventoryStats::getTwoMonthsQuantity).sum();
        Long oneMonthQuantity = inventoryStats.stream().mapToLong(StoreInventoryStats::getOneMonthQuantity).sum();
        Long thisMonthQuantity = inventoryStats.stream().mapToLong(StoreInventoryStats::getThisMonthQuantity).sum();
        Long total = exceedFourMonthsQuantity + threeMonthsQuantity + twoMonthsQuantity + oneMonthQuantity + thisMonthQuantity;

        List<PieData> dataSource = new ArrayList<>();
        PieData exceedFourMonths = new PieData();
        DataInfo percent = exceedFourMonthsQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(exceedFourMonthsQuantity, total);

        exceedFourMonths.setName("四个月前 " + percent.getValue() + percent.getTail() + percent.getUnit());
        exceedFourMonths.setRatio(DomUtil.numberFormat(exceedFourMonthsQuantity, total));
        exceedFourMonths.setValue(DomUtil.quantityFormatJian(exceedFourMonthsQuantity) + "件");
        dataSource.add(exceedFourMonths);

        PieData threeMonths = new PieData();
        percent = threeMonthsQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(threeMonthsQuantity, total);
        threeMonths.setName("前三个月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        threeMonths.setRatio(DomUtil.numberFormat(threeMonthsQuantity, total));
        threeMonths.setValue(DomUtil.quantityFormatJian(threeMonthsQuantity) + "件");
        dataSource.add(threeMonths);

        PieData twoMonths = new PieData();
        percent = twoMonthsQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(twoMonthsQuantity, total);
        twoMonths.setName("前两个月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        twoMonths.setRatio(DomUtil.numberFormat(twoMonthsQuantity, total));
        twoMonths.setValue(DomUtil.quantityFormatJian(twoMonthsQuantity) + "件");
        dataSource.add(twoMonths);

        PieData oneMonth = new PieData();
        percent = oneMonthQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(oneMonthQuantity, total);
        oneMonth.setName("前一个月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        oneMonth.setRatio(DomUtil.numberFormat(oneMonthQuantity, total));
        oneMonth.setValue(DomUtil.quantityFormatJian(oneMonthQuantity) + "件");
        dataSource.add(oneMonth);

        PieData thisMonth = new PieData();
        percent = thisMonthQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(thisMonthQuantity, total);
        thisMonth.setName("当月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        thisMonth.setRatio(DomUtil.numberFormat(thisMonthQuantity, total));
        thisMonth.setValue(DomUtil.quantityFormatJian(thisMonthQuantity) + "件");
        dataSource.add(thisMonth);

        PieInfo info = new PieInfo();
        info.setId("storeProDate");
        info.setName("网点库存生产月份");
        info.setContent(dataSource);
        return info;
    }

    //构建生产日期饼图
    private PieInfo buildWarehouseInventoryDom(List<WarehouseInventoryStats> inventoryStats) {
        Long exceedThreeMonthsQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getExceedThreeMonthsQuantity).sum();
        Long earlyTwoMonthsQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getEarlyTwoMonthsQuantity).sum();
        Long midTwoMonthsQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getMidTwoMonthsQuantity).sum();
        Long lateTwoMonthsQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getLateTwoMonthsQuantity).sum();
        Long earlyOneMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getEarlyOneMonthQuantity).sum();
        Long midOneMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getMidOneMonthQuantity).sum();
        Long lateOneMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getLateOneMonthQuantity).sum();
        Long earlyThisMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getEarlyThisMonthQuantity).sum();
        Long midThisMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getMidThisMonthQuantity).sum();
        Long lateThisMonthQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getLateThisMonthQuantity).sum();
        Long total = exceedThreeMonthsQuantity + earlyTwoMonthsQuantity + midTwoMonthsQuantity + lateTwoMonthsQuantity + earlyOneMonthQuantity
             + midOneMonthQuantity + lateOneMonthQuantity + earlyThisMonthQuantity + midThisMonthQuantity + lateThisMonthQuantity;

        List<PieData> dataSource = new ArrayList<>();
        PieData threeMonthAgo = new PieData();
        DataInfo percent = exceedThreeMonthsQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(exceedThreeMonthsQuantity, total);
        threeMonthAgo.setName("三个月前 " + percent.getValue() + percent.getTail() + percent.getUnit());
        threeMonthAgo.setRatio(DomUtil.numberFormat(exceedThreeMonthsQuantity, total));
        DataInfo exceedThreeMonthsDataInfo = DomUtil.quantityFormat(exceedThreeMonthsQuantity);
        threeMonthAgo.setValue(exceedThreeMonthsDataInfo.getValue().concat(exceedThreeMonthsDataInfo.getTail()).concat(exceedThreeMonthsDataInfo.getUnit()));
        //threeMonthAgo.setValue(DomUtil.quantityFormatWan(exceedThreeMonthsQuantity)+"万件");
        dataSource.add(threeMonthAgo);

        PieData twoMonths = new PieData();
        Long twoMonthsQuantity = earlyTwoMonthsQuantity + midTwoMonthsQuantity + lateTwoMonthsQuantity;
        percent = twoMonthsQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(twoMonthsQuantity, total);
        twoMonths.setName("前两个月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        twoMonths.setRatio(DomUtil.numberFormat(twoMonthsQuantity, total));
        DataInfo twoMonthsDataInfo = DomUtil.quantityFormat(twoMonthsQuantity);
        twoMonths.setValue(
            twoMonthsDataInfo.getValue().concat(twoMonthsDataInfo.getTail()).concat(twoMonthsDataInfo.getUnit()));
        //twoMonths.setValue(DomUtil.quantityFormatWan(twoMonthsQuantity)+"万件");
        dataSource.add(twoMonths);

        PieData OneMonth = new PieData();
        Long oneMonthQuantity = earlyOneMonthQuantity + midOneMonthQuantity + lateOneMonthQuantity;
        percent = oneMonthQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(oneMonthQuantity, total);
        OneMonth.setName("前一个月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        OneMonth.setRatio(DomUtil.numberFormat(oneMonthQuantity, total));
        DataInfo oneMonthDataInfo = DomUtil.quantityFormat(oneMonthQuantity);
        OneMonth.setValue(
            oneMonthDataInfo.getValue().concat(oneMonthDataInfo.getTail()).concat(oneMonthDataInfo.getUnit()));
        //OneMonth.setValue(DomUtil.quantityFormatWan(oneMonthQuantity)+"万件");
        dataSource.add(OneMonth);

        PieData thisMonth = new PieData();
        Long thisMonthQuantity = earlyThisMonthQuantity + midThisMonthQuantity + lateThisMonthQuantity;
        percent = thisMonthQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(thisMonthQuantity, total);
        thisMonth.setName("当月 " + percent.getValue() + percent.getTail() + percent.getUnit());
        thisMonth.setRatio(DomUtil.numberFormat(thisMonthQuantity, total));
        DataInfo thisMonthDataInfo = DomUtil.quantityFormat(thisMonthQuantity);
        thisMonth.setValue(
            thisMonthDataInfo.getValue().concat(thisMonthDataInfo.getTail()).concat(thisMonthDataInfo.getUnit()));
        //thisMonth.setValue(DomUtil.quantityFormatWan(thisMonthQuantity)+"万件");
        dataSource.add(thisMonth);

        PieInfo info = new PieInfo();
        info.setId("wareProDate");
        info.setName("总在仓生产");
        info.setContent(dataSource);
        return info;
    }

    //构建大日期饼图
    private PieInfo buildExpiredPie(List<WarehouseInventoryStats> inventoryStats) {
        Long thirdExpiredQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getThirdExpiredQuantity).sum();
        Long fourthExpiredQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getFourthExpiredQuantity).sum();
        Long normalQuantity = inventoryStats.stream().mapToLong(WarehouseInventoryStats::getNormalQuantity).sum();
        Long total = thirdExpiredQuantity + fourthExpiredQuantity + normalQuantity;

        List<PieData> dataSource = new ArrayList<>();
        PieData thirdExpired = new PieData();
        DataInfo percent = thirdExpiredQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(thirdExpiredQuantity,total);
        thirdExpired.setName("超保1/3 " + percent.getValue() + percent.getTail() + percent.getUnit());
        thirdExpired.setRatio(DomUtil.numberFormat(thirdExpiredQuantity, total));
        DataInfo thirdQuantity = DomUtil.quantityFormat(thirdExpiredQuantity);
        thirdExpired.setValue(thirdQuantity.getValue().concat(thirdQuantity.getTail()).concat(thirdQuantity.getUnit()));
        dataSource.add(thirdExpired);

        PieData fourthExpired = new PieData();
        percent = fourthExpiredQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(fourthExpiredQuantity,total);
        fourthExpired.setName("超保1/4 " + percent.getValue() + percent.getTail() + percent.getUnit());
        fourthExpired.setRatio(DomUtil.numberFormat(fourthExpiredQuantity, total));
        DataInfo fourthQuantity = DomUtil.quantityFormat(fourthExpiredQuantity);
        fourthExpired.setValue(fourthQuantity.getValue().concat(fourthQuantity.getTail()).concat(fourthQuantity.getUnit()));
        dataSource.add(fourthExpired);

        PieData normal = new PieData();
        percent = normalQuantity <= 0 ? this.initDataInfo() : DomUtil.decimalFormat(normalQuantity, total);
        normal.setName("正常量 " + percent.getValue() + percent.getTail() + percent.getUnit());
        normal.setRatio(DomUtil.numberFormat(normalQuantity, total));
        DataInfo normalInfo = DomUtil.quantityFormat(normalQuantity);
        normal.setValue(normalInfo.getValue().concat(normalInfo.getTail()).concat(normalInfo.getUnit()));
        dataSource.add(normal);

        PieInfo info = new PieInfo();
        info.setId("wareExpiredDate");
        info.setName("在仓大日期库存");
        info.setContent(dataSource);
        return info;
    }

    //网点top10排行
    private RankAppComponent buildStoreRank(String sortField,List<StoreInventoryStats> storeInventoryStats,Map<String,List<StoreInventoryStats>> channelStoreStatsMap,Map<String,ChannelSDO> channelMap) {
        RankAppComponent component = new RankAppComponent();
        List topTitles = sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)?Arrays.asList(arrayThreeMonth):Arrays.asList(arrayFourMonth);
        String str = sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)?"前三个月":"四个月前";
        component.setTopName(str+"TOP10库存网点");

        List<RankAppComponentData> topDataList = new ArrayList<>();
        RankAppComponentData tabData = new RankAppComponentData();
        tabData.setTabId("A");
        tabData.setTabName("全业务渠道库存");
        tabData.setTopTitles(topTitles);
        tabData.setContent(assembleRankAppComponentContent(storeInventoryStats,sortField));
        topDataList.add(tabData);

        for (Map.Entry<String,List<StoreInventoryStats>> m : channelStoreStatsMap.entrySet()) {
            String channelCode = m.getKey();
            List<StoreInventoryStats> channelStoreStats = m.getValue();
            ChannelSDO channelSDO = channelMap.get(channelCode);
            if(Objects.isNull(channelSDO)){
                continue;
            }
            RankAppComponentData channelTabData = new RankAppComponentData();
            channelTabData.setTabId(channelCode);
            channelTabData.setTabName(channelSDO.getChannelName()+"渠道库存");
            channelTabData.setTopTitles(topTitles);
            channelTabData.setContent(assembleRankAppComponentContent(channelStoreStats,sortField));
            topDataList.add(channelTabData);

        }
        component.setTopData(topDataList);
        return component;
    }

    private List<RankAppComponentContent> assembleRankAppComponentContent(List<StoreInventoryStats> storeInventoryStats,String sortField){
        List<StoreInventoryStats> storeStats = new ArrayList<>();
        Long maxOne = 0L;
        if(sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)){
            storeStats = storeInventoryStats.stream().filter(x->!x.getThreeMonthsQuantity().equals(0L)).sorted(
                    Comparator.comparing(StoreInventoryStats::getThreeMonthsQuantity).reversed()).collect(Collectors.toList());
            maxOne = CollectionUtils.isNotEmpty(storeStats) ? storeStats.get(0).getThreeMonthsQuantity(): 0L;
        }else{
            storeStats = storeInventoryStats.stream().filter(x->!x.getFourMonthsQuantity().equals(0L)).sorted(
                    Comparator.comparing(StoreInventoryStats::getFourMonthsQuantity).reversed()).collect(Collectors.toList());
            maxOne = CollectionUtils.isNotEmpty(storeStats) ? storeStats.get(0).getFourMonthsQuantity(): 0L;
        }
        storeStats = storeStats.size() > 10 ? storeStats.subList(0, 10) : storeStats;
        //        Long last = threeMonthStats.get(0).getThreeMonthsQuantity();
        //        Integer lastNo = 0;
        Integer sortNo = 0;
        List<RankAppComponentContent> contentList = new ArrayList<>();
        for (StoreInventoryStats stats : storeStats) {
            sortNo++;
            Long quantity = sortField.equals(RANK_SORTFIELD_THREEMONTHSQUANTITY)?stats.getThreeMonthsQuantity():stats.getFourMonthsQuantity();
            RankAppComponentContent data = new RankAppComponentContent();
            if (maxOne > 0) {
                BigDecimal process = new BigDecimal(quantity).multiply(new BigDecimal(100))
                        .divide(new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                data.setRatio(String.valueOf(process));
            }
            data.setSortNo(sortNo);
            //            if (sortNo!=1 && stats.getThreeMonthsQuantity().equals(last)){
            //                data.setSortNo(lastNo);
            //            }
            //            lastNo = data.getSortNo();
            //            last = stats.getThreeMonthsQuantity();
            data.setName(stats.getStoreName());
            data.setNum(DomUtil.quantityFormatJian(quantity));
            contentList.add(data);
        }
        return contentList;
    }

    //货品top10排行
    private RankAppComponent buildGoodsRank(List<StoreInventoryDetail> storeInventoryDetailList) {
        RankAppComponent component = new RankAppComponent();
        component.setTopName("TOP10库存货品");
        List<RankAppComponentData> topData = new ArrayList<>();
        RankAppComponentData threeTab = new RankAppComponentData();
        threeTab.setTabId("threeMonthsRank");
        threeTab.setTabName("前三个月库存");
        threeTab.setTopTitles(Arrays.asList(arrayThreeMonth));
        List<StoreInventoryDetail> sumByGoodsIdList = new ArrayList<>();
        Map<String, List<StoreInventoryDetail>> mapGoods = storeInventoryDetailList.stream().collect(
            Collectors.groupingBy(x -> x.getGoodsId()));
        for (Map.Entry<String, List<StoreInventoryDetail>> entry : mapGoods.entrySet()) {
            StoreInventoryDetail sumByGoodsId = new StoreInventoryDetail();
            List<StoreInventoryDetail> subList = entry.getValue();
            sumByGoodsId.setGoodsName(subList.get(0).getGoodsName());
            Long threeMonthSum = subList.stream().mapToLong(StoreInventoryDetail::getThreeMonthsQuantity).sum();
            sumByGoodsId.setThreeMonthsQuantity(threeMonthSum);
            Long fourMonthSum = subList.stream().mapToLong(StoreInventoryDetail::getFourMonthsQuantity).sum();
            sumByGoodsId.setFourMonthsQuantity(fourMonthSum);
            sumByGoodsIdList.add(sumByGoodsId);
        }
        List<StoreInventoryDetail> threeMonthStats = sumByGoodsIdList.stream().filter(x->!x.getThreeMonthsQuantity().equals(0L))
                .sorted(Comparator.comparing(StoreInventoryDetail::getThreeMonthsQuantity).reversed()).collect(Collectors.toList());
        threeMonthStats = threeMonthStats.size() > 10 ? threeMonthStats.subList(0, 10) : threeMonthStats;
        Long maxOne = CollectionUtils.isNotEmpty(threeMonthStats) ? threeMonthStats.get(0).getThreeMonthsQuantity(): 0L;
        //        Long last = threeMonthStats.get(0).getThreeMonthsQuantity();
        //        Integer lastNo = 0;
        Integer sortNo = 0;
        List<RankAppComponentContent> content = new ArrayList<>();
        for (StoreInventoryDetail stats : threeMonthStats) {
            sortNo++;
            RankAppComponentContent data = new RankAppComponentContent();
            if (maxOne > 0) {
                BigDecimal process = new BigDecimal(stats.getThreeMonthsQuantity()).multiply(new BigDecimal(100))
                    .divide(new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                data.setRatio(String.valueOf(process));
            }
            data.setSortNo(sortNo);
            //            if (sortNo!=1 && stats.getThreeMonthsQuantity().equals(last)){
            //                data.setSortNo(lastNo);
            //            }
            //            lastNo = data.getSortNo();
            //            last = stats.getThreeMonthsQuantity();
            data.setName(stats.getGoodsName());
            data.setNum(DomUtil.quantityFormatJian(stats.getThreeMonthsQuantity()));
            content.add(data);
        }
        threeTab.setContent(content);
        topData.add(threeTab);

        RankAppComponentData fourTab = new RankAppComponentData();
        fourTab.setTabId("fourMonthsRank");
        fourTab.setTabName("四个月前库存");
        fourTab.setTopTitles(Arrays.asList(arrayFourMonth));
        List<StoreInventoryDetail> fourMonthStats = sumByGoodsIdList.stream().filter(x->!x.getFourMonthsQuantity().equals(0L))
                .sorted(Comparator.comparing(StoreInventoryDetail::getFourMonthsQuantity).reversed()).collect(Collectors.toList());
        fourMonthStats = fourMonthStats.size() > 10 ? fourMonthStats.subList(0, 10) : fourMonthStats;
        maxOne = CollectionUtils.isNotEmpty(fourMonthStats) ? fourMonthStats.get(0).getFourMonthsQuantity() : 0L;
        //        last = fourMonthStats.get(0).getFourMonthsQuantity();
        sortNo = 0;
        List<RankAppComponentContent> fourContent = new ArrayList<>();
        for (StoreInventoryDetail stats : fourMonthStats) {
            RankAppComponentContent info = new RankAppComponentContent();
            sortNo++;
            if (maxOne > 0) {
                BigDecimal process = new BigDecimal(stats.getFourMonthsQuantity()).multiply(new BigDecimal(100)).divide(
                    new BigDecimal(maxOne), 2, RoundingMode.HALF_UP);
                info.setRatio(String.valueOf(process));
            }
            info.setSortNo(sortNo);
            //            if (sortNo!=1 && stats.getFourMonthsQuantity().equals(last)){
            //                info.setSortNo(lastNo);
            //            }
            //            lastNo = info.getSortNo();
            //            last = stats.getFourMonthsQuantity();
            info.setName(stats.getGoodsName());
            info.setNum(DomUtil.quantityFormatJian(stats.getFourMonthsQuantity()));
            fourContent.add(info);
        }
        fourTab.setContent(fourContent);
        topData.add(fourTab);
        component.setTopData(topData);
        return component;
    }

    //构建电商平台饼图
    private ModuleInfo buildPlatformPie() {
        ModuleInfo moduleInfo = new ModuleInfo();
        moduleInfo.setTitle("各平台大日期总量占比");
        moduleInfo.setDisplay(false);
        StatisByPlatformRequest request = new StatisByPlatformRequest();
        request.setStatisticalDate(DomUtil.getToday());
        Result<List<EcInventoryStats>> listResult = ecInventoryStatsService.statisByPlatform(request);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
            return moduleInfo;
        }
        Long totalApproach = listResult.getResult().stream().mapToLong(EcInventoryStats::getApproachExpiredQuantity).sum();
        Long totalExpired = listResult.getResult().stream().mapToLong(EcInventoryStats::getThirdExpiredQuantity).sum();
        Long total = totalApproach + totalExpired;
        if (total == 0) {
            return moduleInfo;
        }
        List<DataInfo> dataSource = new ArrayList<>();
        for (EcInventoryStats ecInventoryStats : listResult.getResult()) {
            DataInfo dataInfo = new DataInfo();
            dataInfo.setLabel(ecInventoryStats.getPlatformName());
            Long temp = ecInventoryStats.getApproachExpiredQuantity() + ecInventoryStats.getThirdExpiredQuantity();
            if (temp == 0) {
                continue;
            }
            dataInfo.setValue(DomUtil.numberFormat(temp, total));
            dataSource.add(dataInfo);
        }
        moduleInfo.setDataSource(dataSource);
        moduleInfo.setDisplay(true);
        return moduleInfo;
    }

    //构建电商平台排行榜
    private List<InventoryRankInfo> buildRankInfo() {
        List<InventoryRankInfo> rankInfoList = new ArrayList<>();
        StaticByPlatformAndGoodsRequest request = new StaticByPlatformAndGoodsRequest();
        request.setStatisticalDate(DomUtil.getToday());
        Result<List<EcInventoryDetail>> listResult = ecInventoryDetailService.staticByPlatformAndGoods(request);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
            return rankInfoList;
        }
        List<EcInventoryDetail> details = listResult.getResult();
        //取排名第一超期数量
        Long totalApproach = details.get(0).getThirdExpiredQuantity();
        List<String> goodsIdList = details.stream().map(EcInventoryDetail::getGoodsId).collect(Collectors.toList());
        GetPlatformByGoodsIdRequest byGoodsIdRequest = new GetPlatformByGoodsIdRequest();
        byGoodsIdRequest.setStatisticalDate(DomUtil.getToday());
        byGoodsIdRequest.setGoodsIdList(goodsIdList);
        Result<List<EcInventoryDetail>> platformList = ecInventoryDetailService.getPlatformByGoodsId(byGoodsIdRequest);
        Map<String, List<EcInventoryDetail>> mapGoods = platformList.getResult().stream().collect(Collectors.groupingBy(x -> x.getGoodsId()));
        for (EcInventoryDetail detail : details) {
            InventoryRankInfo rankInfo = new InventoryRankInfo();
            rankInfo.setGoodsId(detail.getGoodsId());
            rankInfo.setGoodsName(detail.getGoodsName());
            Long quantity = detail.getThirdExpiredQuantity();
            rankInfo.setQuantity(DomUtil.thousandthFormat(quantity));
            rankInfo.setRatio(DomUtil.numberFormat(quantity, totalApproach));
            List<String> names = mapGoods.get(detail.getGoodsId()).stream().map(EcInventoryDetail::getPlatformName).collect(Collectors.toList());
            rankInfo.setRemark(String.join(",", names));
            rankInfoList.add(rankInfo);
        }
        return rankInfoList;
    }

    private List<OrganizationSDO> getBranchCompanyList() {
        Result<List<OrganizationSDO>> listResult = otsPlatformEnhanceService.getLoginEmployeeBusinessUnitsSort();
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
            throw new RuntimeException("登录账号没有分公司权限");
        }
        log.info("getLoginEmployeeBusinessUnits_listResult={}", JSON.toJSONString(listResult));
        return listResult.getResult();
    }

    private String getBranchCompanyName(List<OrganizationSDO> organizationSDOS, String branchCompanyId) {
        for (OrganizationSDO sdo : organizationSDOS) {
            if (sdo.getId().equals(branchCompanyId)) {
                return sdo.getName();
            }
        }
        return null;
    }

    private List<DataInfo> initExpiredData() {
        List<DataInfo> dataSource = new ArrayList<>();

        DataInfo thirdExpiredNode = new DataInfo();
        thirdExpiredNode.setLabel("超保1/3库存");
        dataSource.add(thirdExpiredNode);

        DataInfo fourthExpiredNode = new DataInfo();
        fourthExpiredNode.setLabel("超保1/4库存");
        dataSource.add(fourthExpiredNode);

        DataInfo approachExpiredNode = new DataInfo();
        approachExpiredNode.setLabel("总临期库存");
        dataSource.add(approachExpiredNode);
        return dataSource;
    }

    private DataInfo initDataInfo() {
        DataInfo dataInfo = new DataInfo();
        dataInfo.setValue("0");
        dataInfo.setTail(".00");
        dataInfo.setUnit("%");
        return dataInfo;
    }
}
